#pragma once
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
#include <thread>
#include <map>
#include <mutex>
#include <functional>

typedef websocketpp::server<websocketpp::config::asio> WsServer;


using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef WsServer::message_ptr message_ptr;


class WebsocketServer {
public:
	enum Status
	{
		STOP = 0,
		START_LISTEN = 1,
		LISTENING = 2,
		FAIL = 3,
	};

    typedef std::function<void(std::string addr, uint32_t port)> OnNewConnectionHanlder;
	typedef std::function<void(std::string addr, uint32_t port)> OnConnectionCloseHanlder;
	typedef std::function<void(std::string addr, uint32_t port,std::string message)> OnMessageHanlder;
    
    std::string Url();
    uint32_t Port();
    WebsocketServer(std::string server,uint32_t port);
    ~WebsocketServer();
    friend void on_new_connection(WebsocketServer* s, websocketpp::connection_hdl hdl);
    friend void on_message(WebsocketServer* s, websocketpp::connection_hdl hdl, message_ptr msg);
    friend void on_connection_close(WebsocketServer* s, websocketpp::connection_hdl hdl);
	friend void on_connection_fail(WebsocketServer* s, websocketpp::connection_hdl hdl);

    int SendData(uint32_t,const char *data,int len,websocketpp::frame::opcode::value);
    int SendDataAllClient(const char *data,int len,websocketpp::frame::opcode::value);
    void SetOnNewConnectionHanlder(OnNewConnectionHanlder);
    void SetOnConnectionCloseHanlder(OnConnectionCloseHanlder);
    void SetOnMessageHanlder(OnMessageHanlder);
private:
    std::string m_url;  // 地址
    uint32_t m_port;  // url
    WsServer *m_server;
    std::thread *m_thread;
    std::mutex m_mutex;
    OnNewConnectionHanlder m_on_connection;
    OnConnectionCloseHanlder m_on_close;
    OnMessageHanlder m_on_message;
    std::map<uint32_t,websocketpp::connection_hdl> m_clients;
    Status m_status;
};


